﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using PSE.AuditLogging.ContingencyService.Management.ServiceContracts;
using System.ServiceProcess;
using System.Threading;
using PSE.AuditLogging.Common;
using PSE.AuditLogging.Common.Service;

namespace PSE.AuditLogging.ContingencyService.Management
{    
    public class ServiceManager
    {
        private const string SERVICE_NAME = "BM&FBOVESPA Audit Logging Contingency Service";

        public bool Start()
        {
            return this.Start(null);
        }

        public bool Start(TimeSpan? timeout)
        {
            using (ServiceController controller = new ServiceController(SERVICE_NAME))
            {
                if (controller.Status == ServiceControllerStatus.Stopped)
                {
                    controller.Start();

                    controller.Refresh();

                    DateTime utcNow = DateTime.UtcNow;

                    while (controller.Status != System.ServiceProcess.ServiceControllerStatus.Running)
                    {
                        Thread.Sleep(250);
                        controller.Refresh();

                        if (timeout.HasValue && (DateTime.UtcNow - utcNow) > timeout)
                        {
                            throw new System.ServiceProcess.TimeoutException();
                        }

                        if (controller.Status == ServiceControllerStatus.Stopped)
                            break;
                    }
                }

                return controller.Status == ServiceControllerStatus.Running;
            }
        }

        public bool Stop()
        {
            return this.Stop(null);
        }

        public bool Stop(TimeSpan? timeout)
        {
            using (ServiceController controller = new ServiceController(SERVICE_NAME))
            {
                if (controller.Status == ServiceControllerStatus.Running)
                {
                    controller.Stop();

                    controller.Refresh();

                    if (timeout.HasValue)
                        controller.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped, timeout.Value);
                    else
                        controller.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);

                }

                return controller.Status == ServiceControllerStatus.Stopped;
            }
        }

        public bool IsRunning()
        {
            using (ServiceController controller = new ServiceController(SERVICE_NAME))
            {
                return controller.Status == ServiceControllerStatus.Running;
            }
        }

        public bool StartProduct(string productId)
        {
            using (ServiceClientProxyFactory<IServiceManager> proxyFactory = new ServiceClientProxyFactory<IServiceManager>(Constants.SERVICE_MANAGER_NETPIPE_ADDRESS))
            {
                return proxyFactory.CreateProxy().StartProduct(productId);
            }
        }

        public bool StopProduct(string productId)
        {
            using (ServiceClientProxyFactory<IServiceManager> proxyFactory = new ServiceClientProxyFactory<IServiceManager>(Constants.SERVICE_MANAGER_NETPIPE_ADDRESS))
            {
                return proxyFactory.CreateProxy().StopProduct(productId);
            }
        }

        public bool RestartProduct(string productId)
        {
            using (ServiceClientProxyFactory<IServiceManager> proxyFactory = new ServiceClientProxyFactory<IServiceManager>(Constants.SERVICE_MANAGER_NETPIPE_ADDRESS))
            {
                return proxyFactory.CreateProxy().RestartProduct(productId);
            }
        }

        public List<string> GetRunningProducts()
        {
            using (ServiceClientProxyFactory<IServiceManager> proxyFactory = new ServiceClientProxyFactory<IServiceManager>(Constants.SERVICE_MANAGER_NETPIPE_ADDRESS))
            {
                return proxyFactory.CreateProxy().GetRunningProducts();
            }
        }
    }
}
